package com.charging.business.service;

import com.charging.business.config.MinFeeManager;
import com.charging.business.enums.Issuer;
import com.charging.business.exception.CustomizeException;
import com.charging.business.jin.JinOnLineRequest;
import com.charging.business.qin.Db3FileUtils;
import com.charging.business.qin.QinOnLineRequest;
import com.charging.business.utils.RosterUtils;
import com.charging.business.utils.PayUtil;
import com.charging.business.vo.CustomOnlineResponse;
import com.charging.business.vo.FeeExCalcRequest;
import com.charging.business.vo.FeeExCalcResponse;
import com.charging.business.vo.obj.MiniFeeInfo;
import com.charging.business.vo.obj.OnlineFeeInfo;
import com.charging.business.vo.obj.SplitProvinceMini;
import com.charging.common.utils.DateUtils;
import com.charging.common.utils.uuid.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

/**
 * @author JerryLu
 * @date 2024/9/27 11:15
 * @description 纸券通行计费
 */
@Component
public class FeeExSpcHandle {
    private static final Logger logger = LoggerFactory.getLogger(FeeExSpcHandle.class);

    private static boolean beWantMinFee = false;

    // 出口车型
    public int exVehicleType = 0;

    // 出口轴数
    public int exAxleCount = 0;

    // 入口时间
    public Date enTime;

    // 出口时间
    public Date exTime;

    @Autowired
    private MinFeeManager minFeeManager;

    @Autowired
    private Db3FileUtils db3FileUtils;

    @Autowired
    private RosterUtils rosterUtils;


    public FeeExCalcResponse run(FeeExCalcRequest request, FeeExCalcResponse response) throws Exception {
        // 1、对入出口时间、车牌、车型、轴数、车种、发行方等先批量处理
        this.init(request);
        // 2、兜底计费
        long s1 = System.currentTimeMillis();
        response = this.getMinFee(request, response);
        long s2 = System.currentTimeMillis();
        logger.info("最小费额算费结束,耗时{}毫秒", s2 - s1);
        // 3、在线特情计费
        response = this.specialFee(request, response);

        return response;
    }

    /**
     * 批量处理基本数据，设置异常特情
     *
     * @param request
     */
    public void init(FeeExCalcRequest request) {
        exTime = DateUtils.dateTime(DateUtils.YYYY_MM_DD_TT_HH_MM_SS, request.getExTime());
//        enVehicleId = BasicUtil.formatVehicleId(request.cpcEf01Model.enVPlate());
//        exVehicleId = BasicUtil.formatVehicleId(request.getVehicleId());
        //入出口车牌对比
//        if (!BasicUtil.compareVehicleId(exVehicleId, enVehicleId, false)) {
//            BasicUtil.setSpecialInfo(SpecialSituation.TYPE52.getValue());
//        }

        // 入出口车型、轴数
        exVehicleType = request.getExVehicleType();
        exAxleCount = request.getExAxleCount();
    }

    /**
     * 兜底计费，分省合并
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    public FeeExCalcResponse getMinFee(FeeExCalcRequest request, FeeExCalcResponse response) throws Exception {
        // 获取最小费额版本号
        boolean bETC = true;
        try {
            MiniFeeInfo miniFeeInfo = new MiniFeeInfo();
            String minVersion = minFeeManager.getCurrentVersion();
            miniFeeInfo.spcRateVersion = minVersion;
            ArrayList<SplitProvinceMini> minProvinces = new ArrayList<>();
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                //陕西
                try {
                    db3FileUtils.loadDb3File(request.getEnStationId(), request.getExStationId(), exVehicleType);
                    minProvinces = minFeeManager.getMinFee(bETC, request.getEnStationId(), request.getExStationId(), exVehicleType);
                } catch (Exception e) {
                    throw new CustomizeException("获取最小费额失败");
                }
            } else {
                minProvinces = rosterUtils.getMiniFee(request.getEnStationId(), request.getExStationId(), exVehicleType, exAxleCount, bETC);
            }

            if (minProvinces.isEmpty()) {
                throw new CustomizeException("获取兜底计费失败：查询不到对应的出口计费信息");
            }
            // 汇总最小费额信息
            for (SplitProvinceMini prov : minProvinces) {
                miniFeeInfo.zMinPayFee += prov.ziMinPayFee;
                miniFeeInfo.zMinFee += prov.ziMinFee;
                miniFeeInfo.calMinFeeFee += prov.calMinFeeFee;
                miniFeeInfo.calMinFeeFee95 += prov.calMinFeeFee95;
                miniFeeInfo.calMinFeeMileage += prov.calMinFeeMileage;
            }
            miniFeeInfo.splitProvince = minProvinces;
            //陕西合并分省信息
            if (request.getExStationHex().startsWith(Issuer.Issue610101.getProvinceCode())) {
                miniFeeInfo.merge();
            }

            response.setSpcRateVersion(minVersion);
            response.setRateVersion(miniFeeInfo.splitProvince.get(miniFeeInfo.splitProvince.size() - 1).rateVersion);
            response.setMiniFeeInfo(miniFeeInfo);
            response.setExitFeeType(6);
            float temp = (float) miniFeeInfo.calMinFeeMileage / 1000 / 80;
            int tmp = temp < 1 ? 1 : Math.round(temp + 1);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(exTime);
            calendar.add(Calendar.HOUR_OF_DAY, -tmp);
            enTime = calendar.getTime();
            logger.info("最小费额结果：通行省份个数：{}，总应收：{}元，总实收：{}元，95折总实收：{}元，总里程：{}元，费额费率版本号：{}", miniFeeInfo.splitProvince.size(), PayUtil.convertFee(miniFeeInfo.calMinFeeFee), PayUtil.convertFee(miniFeeInfo.zMinFee), PayUtil.convertFee(miniFeeInfo.calMinFeeFee95), PayUtil.convertMileage(miniFeeInfo.calMinFeeMileage), minVersion);
        } catch (Exception e) {
            throw new CustomizeException(!e.getMessage().isEmpty() ? e.getMessage() : "获取兜底计费异常");
        }
        return response;
    }

    /**
     * 在线特情计费，分省合并
     *
     * @param request
     * @throws CustomizeException
     */
    public FeeExCalcResponse specialFee(FeeExCalcRequest request, FeeExCalcResponse response) throws CustomizeException {
        OnlineFeeInfo onlineFeeInfo = new OnlineFeeInfo();
        CustomOnlineResponse spececReponse = new CustomOnlineResponse();
        long s1 = System.currentTimeMillis();
        if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
            JinOnLineRequest onLineRes = new JinOnLineRequest();
            onLineRes.setMediaId(request.getMediaNo());
            onLineRes.setExStationId(request.getExStationHex() + "|" + request.getExStationId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleClass(request.getVehicleClass());
            if (request.getPayType() != null) {
                onLineRes.setPayType(request.getPayType());
            }
            onLineRes.setPassId(request.getPassId());
            onLineRes.setEnStationId(request.getEnStationHex() + "|" + request.getEnStationId());
            onLineRes.setFeeType(1);
            onLineRes.setAxleCount(request.getExAxleCount());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setSecondConfirm(1);
            onLineRes.setIsETC(request.getIsDiscount());
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setEnTollLaneId(request.getEnTollLaneId());
            onLineRes.setExTollLaneId(request.getExTollLaneId());
            onLineRes.setIsMultiProv(1);
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setIssuerId(request.getIssuerId());
            onLineRes.setReqVersion(Long.parseLong(DateUtils.dateTime()));
            onLineRes.setVehicleSign(request.getVehicleSign());
            spececReponse = rosterUtils.getJinExOnlineFee(onLineRes, response);
        } else {
            QinOnLineRequest onLineRes = new QinOnLineRequest();
            onLineRes.setRequestId(IdUtils.fastSimpleUUID());
//            onLineRes.setSplitProvince(IdUtils.fastSimpleUUID());
            onLineRes.setRequestType(11);
            if (request.obuEf04Model != null && request.obuEf04Model.provCount != 0) {
                onLineRes.setMultiProvince(request.obuEf04Model.provCount > 1 ? 1 : 0);
            } else {
                onLineRes.setMultiProvince(9);
            }
            onLineRes.setPassId(request.getPassId());
            onLineRes.setMediaType(request.getMediaType());
            onLineRes.setMediaNo(request.getMediaNo());
            onLineRes.setIssuerId(request.getIssuerId());
            onLineRes.setIsDiscount(request.getIsDiscount());
            onLineRes.setValidShortFee(request.getValidShortFee() == null || request.getValidShortFee() == 1 ? 1 : 2);
            onLineRes.setEnLaneId(request.getEnTollLaneId());
            onLineRes.setEnTime(request.getEnTime());
            onLineRes.setVehicleId(request.getVehicleId());
            onLineRes.setExLaneId(request.getExTollLaneId());
            onLineRes.setExTime(request.getExTime());
            onLineRes.setVehicleType(request.getExVehicleType());
            onLineRes.setVehicleUserType(request.getVehicleUserType());
            onLineRes.setAxleCount(request.getExAxleCount());
            spececReponse = rosterUtils.getQinExOnlineFee(onLineRes, response);
        }
        long s2 = System.currentTimeMillis();
        logger.info("在线计费交易算费结束,耗时{}毫秒", s2 - s1);
        if (spececReponse.getOnlineSpececResponse().getCalculateResult() == 1) {
            //设置分省金额明细
            onlineFeeInfo.setSplitProDetail(spececReponse.getOnlineSpececResponse());
            //合并分省信息
            onlineFeeInfo.merge();
            logger.info("在线计费结果：通行省份个数：{}，总应收：{}元，总实收：{}元，总优惠：{}元，总拆分：{}元，总里程：{}公里", onlineFeeInfo.splitProvince.size(), PayUtil.convertFee(onlineFeeInfo.payFee), PayUtil.convertFee(onlineFeeInfo.fee), PayUtil.convertFee(onlineFeeInfo.discountFee), PayUtil.convertFee(onlineFeeInfo.splitAmount), PayUtil.convertMileage(onlineFeeInfo.feeMileage));
        } else {
            beWantMinFee = true;
            logger.info("在线计费失败,走兜底计费");
            return response;
        }
        int spFee = 0;
        int minFee = 0;
        int spMileage = 0;
        int minMileage = 0;
        //在线计费应收金额
        spFee = onlineFeeInfo.getPayFee();
        //最小费额应收金额
        minFee = response.getMiniFeeInfo().calMinFeeFee;
        //在线计费总里程
        spMileage = onlineFeeInfo.getFeeMileage();
        //最小费额里程
        minMileage = response.getMiniFeeInfo().calMinFeeMileage;

        //是否验证最小费额，请求参数里里带入
        if (request.getValidShortFee() == null || request.getValidShortFee() == 1) {
            if (request.getExStationHex().startsWith(Issuer.Issue140101.getProvinceCode())) {
                //根据山西计费规则。分为客车与6轴以下货车 和6轴以上货车
                if (exVehicleType < 10 || exAxleCount <= 6) {
                    if (spFee >= minFee * 0.9f && spFee <= minFee * 1.5f) {
                        // d)在线计费应收金额大于等于最小费额应收下限值且
                        // 在线计费应收金额小于等于最小费额应收上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage < minMileage * 1.5f) {
                        //e)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程小于最小费额应收里程上限值时使用在线计费金额计费
                        beWantMinFee = false;
                    } else if (spFee >= minFee * 0.9f && spFee > minFee * 1.5f && spMileage > minMileage * 1.5f) {
                        //f)在线计费应收金额大于等于最小费额应收下限值且
                        //在线计费应收金额大于最小费额应收上限值且
                        //在线计费里程大于最小费额应收里程上限值时需要监控授权是否使用在线计费金额，如果监控回控同意则使用
                        logger.info("监控授权...");
//                    beWantMinFee = false;
                    } else {
                        //g)不满足以上条件则转最小费额计费
                        beWantMinFee = true;
                    }
                } else {
                    //6轴以上货车
                    //外省兜底应收金额
                    int otherProMinFee = response.miniFeeInfo.payFeeProvSumOther();
                    //本省兜底应收金额
                    double selfProMinFee = response.miniFeeInfo.payFeeProvSumLocal();
                    // 大于18轴按18轴计算
                    exAxleCount = Math.min(exAxleCount, 18);
                    double selfProMinFee1 = selfProMinFee * (1 + (exAxleCount - 6) * 0.2f);
                    //通行省份个数
                    int proNum = request.obuEf04Model.provCount;
                    double folowFee = (otherProMinFee + selfProMinFee1) - proNum * 50f;
                    beWantMinFee = !(spFee >= folowFee);
                }
            } else {
                //包年车辆：15-绕城包年 16-西阎包年 17-绕城西阎包年
                int vehicleUserType = request.getVehicleUserType();
                int basicAmount = 0;
                double amount = 0;
                double lowAmount;
                double upperAmount = minFee * 5f;
                if (vehicleUserType == 15) {
                    basicAmount = 4371;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 16) {
                    basicAmount = 2825;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else if (vehicleUserType == 17) {
                    basicAmount = 7196;
                    amount = minFee * 0.9f - basicAmount;
                    lowAmount = amount < 0 ? 0 : amount;
                } else {
                    lowAmount = minFee * 0.9f;
                }

                beWantMinFee = !(spFee >= lowAmount) || !(spFee <= upperAmount);
            }
        }

        if (!beWantMinFee) {
            response.setOnlineFeeInfo(onlineFeeInfo);
        } else {
            response.setExitFeeType(6);
        }
        return response;
    }
}
